 
  

 






<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html>

<!-- Mirrored from www.javapractices.com/topic/TopicAction.do;jsessionid=4FCCB481C702D708A7360133D128E359?Id=51 by HTTrack Website Copier/3.x [XR&CO'2010], Sun, 12 Jun 2011 17:28:07 GMT -->
<!-- Added by HTTrack --><meta http-equiv="content-type" content="text/html;charset=UTF-8"><!-- /Added by HTTrack -->
<head>
 <title>
  Java Practices -> Objects communicating across threads
 </title>
 <link rel="stylesheet" type="text/css" href="../stylesheet8.css" media="all">
 
 <link rel="shortcut icon" href='../images/favicon.ico' type="image/vnd.microsoft.icon">
 <meta name="description" content="Concise presentations of java programming practices, tasks, and conventions, amply illustrated with syntax highlighted code examples.">
 
 <meta name='keywords' content='notify,notifyAll,synchronized,wait loop,wait&#045;loop,thread,java,java programming,java practices,java idiom,java style,java design patterns,java coding conventions,'>
 
 
</head>
 
<body>


<div class='menu-bar'>
 
  <a href='../home/HomeAction.html' title='Table of Contents'>Home</a> |
  <a href='../vote/VoteSummaryAction-2.html' title='View Poll Results'>Poll</a> |
   
  <A href='../feedback/FeedbackAction451f-2.html?Operation=Show' title='Send Your Feedback'>Wiki</a> |
  <b><a href='../source/SourceAction-2.html' title='Grab Source Code'>Source Code</a></b><IMG class='no-margin' SRC="../images/goldstar.gif" ALT=""> |

  <a href='http://www.web4j.com/Java_Web_Application_Framework_Overview.jsp?From=1' title='Free Download - Java Web Application Framework'><b>WEB4J</b></a> |
  
  <a href='http://www.date4j.net/' title='Replacement for java.util.Date'><b>DATE4J</b></a> |

   <a href='../references/ReferencesAction-2.html' title='References'>Links</a>
   
  <form action='http://www.javapractices.com/search/SearchAction.do' method='get' class='search-form'>
   <input type='text' name='SearchTerms' value="" size=12 maxlength=50 class='search'>
   <input type='submit' value="Search">
  </form>
 
</div>

<P>



  

 






<p class="display-messages">

 

 

</p>


<div class="main-layout">
 
   

 




<div class='page-title'>Objects communicating across threads</div>

<div class='main-body'>
 
<br>
Since version 1.5, the JDK has included the <a href='http://java.sun.com/javase/6/docs/api/java/util/concurrent/package-summary.html'><tt>java.util.concurrent</tt></a> package.
It was developed by experienced gurus, and includes a number of items for creating many kinds of multi-threaded programs.
<i>Java Concurrency in Practice</i> by Goetz and others is a good reference for this package.

<P>Here's a basic example of using <a href='http://java.sun.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html'><tt>ExecutorService</tt></a> and <a href='http://java.sun.com/javase/6/docs/api/java/util/concurrent/CountDownLatch.html'><tt>CountDownLatch</tt></a> from <tt>java.util.concurrent</tt> to communicate between threads.
The example has the following context: in client side programming, it's common to show the user a list of their available printers. 
However, the JDK's tool for fetching this information can have poor performance - sometimes resulting in delays of several seconds or more.
So, one option is to fetch the list of available printers early upon startup of the application, in a separate worker thread.
Later, when the user wishes to print something, the list of available printers will already be pre-fetched.
<br>
<PRE>

<span class='keyword'>import</span> java.util.List;
<span class='keyword'>import</span> javax.print.PrintService;

<span class='comment'>/** 
 Toy client application. 
  Needs to present a list of printers to the end user.
  The problem is that fetching the list of printers can take several seconds.
  So, the idea is to start fetching the list in a worker thread upon startup.
*/</span> 
<span class='keyword'>public</span> <span class='keyword'>final</span> <span class='keyword'>class</span> LaunchApplication {

  <span class='keyword'>public</span> <span class='keyword'>static</span> <span class='keyword'>void</span> main(String... aArgs){
    log(<span class='literal'>"Launching application."</span>);
    PrinterListDAO.init(); <span class='comment'>//launches worker thread
</span>    
    <span class='comment'>//construct the user interface, other start tasks, etc...
</span>    
    <span class='comment'>//use the list of printers later in processing
</span>    List&lt;PrintService&gt; printers = <span class='keyword'>new</span> PrinterListDAO().getPrinters();
    log(<span class='literal'>"Seeing this many printers:"</span> + printers.size());
  }
  
  <span class='keyword'>private</span> <span class='keyword'>static</span> <span class='keyword'>void</span> log(String aMsg){
    System.out.println(aMsg);
  }
} 
</PRE>
<br>
<br>
<PRE>

<span class='keyword'>import</span> java.util.List;
<span class='keyword'>import</span> java.util.concurrent.CountDownLatch;
<span class='keyword'>import</span> java.util.concurrent.ExecutorService;
<span class='keyword'>import</span> java.util.concurrent.Executors;
<span class='keyword'>import</span> javax.print.PrintService;

<span class='keyword'>final</span> <span class='keyword'>class</span> PrinterListDAO {

  <span class='comment'>/** This must be called early upon startup. */</span>
  <span class='keyword'>static</span> <span class='keyword'>void</span> init(){
    fLatch = <span class='keyword'>new</span> CountDownLatch(<span class='literal'>1</span>);
    fWorker = <span class='keyword'>new</span> PrinterListWorker(fLatch);
    ExecutorService executor = Executors.newSingleThreadExecutor();
    executor.execute(fWorker);
    executor.shutdown();<span class='comment'>//reclaims resources
</span>  }

  <span class='comment'>/** Return the list of printers that can print PDFs (double-sided, portrait).*/</span>
  List&lt;PrintService&gt; getPrinters(){
    <span class='keyword'>try</span> {
      <span class='comment'>//block until the worker has set the latch to 0:
</span>      fLatch.await();
    }
    <span class='keyword'>catch</span> (InterruptedException ex){
      log(ex.toString());
      Thread.currentThread().interrupt();
    }
    <span class='keyword'>return</span> fWorker.getPrinterList();
  }
  
  <span class='comment'>// PRIVATE
</span>  
  <span class='comment'>/** Used to communicate between threads. */</span>
  <span class='keyword'>static</span> <span class='keyword'>private</span> CountDownLatch fLatch;
  
  <span class='keyword'>static</span> <span class='keyword'>private</span> PrinterListWorker fWorker;
  
  <span class='keyword'>private</span> <span class='keyword'>static</span> <span class='keyword'>void</span> log(String aMsg){
    System.out.println(aMsg);
  }
} 
</PRE>
<br>
<br>
<PRE>

<span class='keyword'>import</span> java.util.*;
<span class='keyword'>import</span> java.util.concurrent.CountDownLatch;
<span class='keyword'>import</span> javax.print.PrintService;
<span class='keyword'>import</span> javax.print.PrintServiceLookup;
<span class='keyword'>import</span> javax.print.attribute.HashPrintRequestAttributeSet;
<span class='keyword'>import</span> javax.print.attribute.PrintRequestAttributeSet;
<span class='keyword'>import</span> javax.print.attribute.standard.OrientationRequested;
<span class='keyword'>import</span> javax.print.attribute.standard.Sides;
<span class='keyword'>import</span> javax.print.DocFlavor;

<span class='comment'>/** Look up the list of printers. */</span>
<span class='keyword'>final</span> <span class='keyword'>class</span> PrinterListWorker <span class='keyword'>implements</span> Runnable {

  <span class='comment'>/** When the work is done, the latch will count down to 0. */</span>
  PrinterListWorker(CountDownLatch aLatch){
    fLatch = aLatch;  
  }
  
  <span class='keyword'>public</span> <span class='keyword'>void</span> run() {
    log(<span class='literal'>"Worker thread started..."</span>);
    <span class='keyword'>long</span> start = System.currentTimeMillis();

    <span class='comment'>//double-sided, portrait, for PDF files.
</span>    PrintRequestAttributeSet attrs = <span class='keyword'>new</span> HashPrintRequestAttributeSet();
    attrs.add(Sides.DUPLEX);
    attrs.add(OrientationRequested.PORTRAIT);
    <span class='comment'>//this can take several seconds in some environments:
</span>    fPrintServices = Arrays.asList(
      PrintServiceLookup.lookupPrintServices(DocFlavor.INPUT_STREAM.PDF, attrs)
     );
    
    <span class='keyword'>long</span> end = System.currentTimeMillis();
    log(<span class='literal'>"Finished fetching list of printers. Millis: "</span> + (end-start));
    log(<span class='literal'>"Num printers found:"</span> + fPrintServices.size());
    fLatch.countDown();
  }

  <span class='comment'>/** Return an unmodifiable list of printers. */</span>
  List&lt;PrintService&gt; getPrinterList(){
    <span class='keyword'>return</span> Collections.unmodifiableList(fPrintServices);
  }
  
  <span class='comment'>// PRIVATE
</span>  
  <span class='comment'>/** Used to communicate between threads. */</span>
  <span class='keyword'>private</span> CountDownLatch fLatch;

  <span class='keyword'>private</span> List&lt;PrintService&gt; fPrintServices;
  
  <span class='keyword'>private</span> <span class='keyword'>static</span> <span class='keyword'>void</span> log(String aMsg){
    System.out.println(aMsg);
  }
} 
</PRE>
<br>
Here's an example run 
<PRE>Launching application.
Worker thread started...
Finished fetching list of printers. Millis: 578
Num printers found:0
Seeing this many printers:0</PRE>

<h3>Older JDKs</h3>
If a modern JDK is not available to you, then you can't use the services of <tt>java.util.concurrent</tt>.
Instead, you will need to rely on other means - often the Thread class, and the <tt>wait</tt> and <tt>notify</tt> 
methods of the Object class.

<P>The following technique uses the <tt>wait-</tt>loop idiom and <tt>notifyAll</tt>. 
To be safe, always use <tt><a href="http://java.sun.com/javase/6/docs/api/java/lang/Object.html#notifyAll()">notifyAll</a></tt>
instead of <tt><a href="http://java.sun.com/javase/6/docs/api/java/lang/Object.html#notify()">notify</a></tt>.
(As an optimization, <tt>notify</tt> can be used instead of <tt>notifyAll</tt>, but only if you know exactly what you are doing.)

<p>Important points :
<ul>
<li>
<tt><a href="http://java.sun.com/javase/6/docs/api/java/lang/Object.html#wait()">wait</a></tt>
and <tt>notifyAll</tt> must always occur within a <tt>synchronized</tt>
block</li>

<li>
<tt>wait</tt> must always be invoked within a <tt>while</tt> loop,&nbsp;
and not in an <tt>if</tt> statement</li>
</ul>
<b>Example</b>

<p>In this example, the <tt>Airplane</tt> always needs to check with the
<tt>Airport</tt>
to see if it has an available runway before it is able to take off or land.
<br>
<PRE>

<span class='comment'>/** Uses wait loop idiom for inter-thread communication. */</span>
<span class='keyword'>public</span> <span class='keyword'>final</span> <span class='keyword'>class</span> Airplane <span class='keyword'>implements</span> Runnable {

  <span class='keyword'>public</span> Airplane ( Airport aAirport, String aFlightId ){
    fAirport = aAirport;
    fFlightId = aFlightId;
  }

  <span class='keyword'>public</span> <span class='keyword'>void</span> run() {
    takeOff();
    fly();
    land();
  }

  <span class='comment'>// PRIVATE ////
</span>  <span class='keyword'>private</span> Airport fAirport;
  <span class='keyword'>private</span> String fFlightId;

  <span class='keyword'>private</span> <span class='keyword'>void</span> takeOff() {
    <span class='keyword'>synchronized</span>( fAirport ) {
      <span class='comment'>//always use a while loop, never an if-statement:
</span>      <span class='keyword'>while</span> ( !fAirport.hasAvailableRunway() ) {
        System.out.println( fFlightId + <span class='literal'>": waiting for runway..."</span> );
        <span class='keyword'>try</span> {
          <span class='comment'>//wait for notification from the airport that
</span>          <span class='comment'>//the state of the airport has changed.
</span>          <span class='comment'>//wait must always occur within a synchronized block
</span>          fAirport.wait();
        }
        <span class='keyword'>catch</span> (InterruptedException ex) {
          Thread.currentThread().interrupt();
          System.err.println( ex );
        }
      }
      <span class='comment'>//there is an available runway now, so we may take off
</span>      System.out.println( fFlightId + <span class='literal'>": taking off now..."</span> );
    }
  }

  <span class='keyword'>private</span> <span class='keyword'>void</span> fly() {
    System.out.println( fFlightId + <span class='literal'>": flying now..."</span> );
    <span class='keyword'>try</span> {
      <span class='comment'>//do nothing for several seconds
</span>      Thread.sleep(<span class='literal'>10000</span>);
    }
    <span class='keyword'>catch</span> ( InterruptedException ex ){
      System.err.println( ex );
      Thread.currentThread().interrupt();
    }
  }

  <span class='keyword'>private</span> <span class='keyword'>void</span> land() {
    <span class='keyword'>synchronized</span>( fAirport ) {
      <span class='keyword'>while</span> ( !fAirport.hasAvailableRunway() ) {
        <span class='comment'>//wait for notification from the airport that
</span>        <span class='comment'>//the state of the airport has changed.
</span>        System.out.println( fFlightId + <span class='literal'>": waiting for runway..."</span> );
        <span class='keyword'>try</span> {
          fAirport.wait();
        }
        <span class='keyword'>catch</span> (InterruptedException ex) {
          System.err.println( ex );
          Thread.currentThread().interrupt();
        }
      }
      <span class='comment'>//there is an available runway now, so we may take off
</span>      System.out.println( fFlightId + <span class='literal'>": landing now..."</span> );
    }
  }
} 
</PRE>
<br>
<br>
<PRE>

<span class='comment'>/** Notifies Airplanes when its state changes. */</span>
<span class='keyword'>public</span> <span class='keyword'>final</span> <span class='keyword'>class</span> Airport <span class='keyword'>implements</span> Runnable {

  <span class='keyword'>public</span> Airport (String aName) {
    <span class='keyword'>super</span>();
    fName = aName;
  }

  <span class='keyword'>public</span> <span class='keyword'>synchronized</span> <span class='keyword'>boolean</span> hasAvailableRunway() {
    <span class='keyword'>return</span> fHasAvailableRunway;
  }

  <span class='keyword'>public</span> <span class='keyword'>void</span> run() {
    System.out.println( <span class='literal'>"Running "</span> + fName + <span class='literal'>" Airport."</span> );
    <span class='keyword'>while</span> (<span class='keyword'>true</span>) {
      <span class='keyword'>try</span> {
        <span class='keyword'>synchronized</span> ( <span class='keyword'>this</span> ) {
          <span class='comment'>//simply toggle the state between available and not available
</span>          fHasAvailableRunway = !fHasAvailableRunway;
          System.out.println(fName + <span class='literal'>" Has Available Runway: "</span> + fHasAvailableRunway);
          <span class='comment'>//notify all waiters of the change of state
</span>          notifyAll();
        }
        <span class='comment'>//pause execution for a few seconds
</span>        Thread.sleep( <span class='literal'>1000</span> );
      }
      <span class='keyword'>catch</span> ( InterruptedException ex ){
        System.err.println( ex );
        Thread.currentThread().interrupt();
      }
    }
  }

  <span class='comment'>//PRIVATE ///
</span>  <span class='keyword'>private</span> <span class='keyword'>boolean</span> fHasAvailableRunway = <span class='keyword'>true</span>;

  <span class='keyword'>private</span> String fName;
} 
</PRE>
<br>
<br>An example run of the following <tt>FlightSimulator</tt> class resulted
in this output :
<p><tt>Running Flight Simulator.</tt>
<br><tt>Terminating the original user thread.</tt>
<br><tt>Running Charles de Gaulle Airport.</tt>
<br><tt>Charles de Gaulle Has Available Runway: false</tt>
<br><tt>Flight 8875: waiting for runway...</tt>
<br><tt>Charles de Gaulle Has Available Runway: true</tt>
<br><tt>Flight 8875: taking off now...</tt>
<br><tt>Flight 8875: flying now...</tt>
<br><tt>Charles de Gaulle Has Available Runway: false</tt>
<br><tt>Charles de Gaulle Has Available Runway: true</tt>
<br><tt>Charles de Gaulle Has Available Runway: false</tt>
<br><tt>Charles de Gaulle Has Available Runway: true</tt>
<br><tt>Charles de Gaulle Has Available Runway: false</tt>
<br><tt>Charles de Gaulle Has Available Runway: true</tt>
<br><tt>Charles de Gaulle Has Available Runway: false</tt>
<br><tt>Charles de Gaulle Has Available Runway: true</tt>
<br><tt>Charles de Gaulle Has Available Runway: false</tt>
<br><tt>Flight 8875: waiting for runway...</tt>
<br><tt>Charles de Gaulle Has Available Runway: true</tt>
<br><tt>Flight 8875: landing now...</tt>
<br><tt>Charles de Gaulle Has Available Runway: false</tt>
<br><tt>Charles de Gaulle Has Available Runway: true</tt>
<br>
<PRE>

<span class='comment'>/**  Builds and starts threads for Airport and Airplanes. */</span>
<span class='keyword'>public</span> <span class='keyword'>final</span> <span class='keyword'>class</span> FlightSimulator {

  <span class='keyword'>public</span> <span class='keyword'>static</span> <span class='keyword'>void</span> main(String... arguments) {
    System.out.println( <span class='literal'>"Running Flight Simulator."</span> );

    <span class='comment'>//build an airport and start it running
</span>    Airport charlesDeGaulle = <span class='keyword'>new</span> Airport(<span class='literal'>"Charles de Gaulle"</span>);
    Thread airport = <span class='keyword'>new</span> Thread( charlesDeGaulle );
    airport.start();

    <span class='comment'>//build a plane and start it running
</span>    Thread planeOne = <span class='keyword'>new</span> Thread( <span class='keyword'>new</span> Airplane(charlesDeGaulle, <span class='literal'>"Flight 8875"</span>) );
    planeOne.start();

    <span class='comment'>//notice that this user thread now ends, but the program itself does
</span>    <span class='comment'>//NOT end since the threads created above are also user
</span>    <span class='comment'>//threads. All user threads have equal status, and there
</span>    <span class='comment'>//is nothing special about the thread which launches a program.
</span>    System.out.println(<span class='literal'>"Terminating the original user thread."</span>);
  }
} 
</PRE>
<br>
<br>
<br>

</div>




<div class='topic-section'>See Also :</div>
<div class='main-body'>
 
  
  <a href='TopicAction4826-2.html?Id=50'>Launch thread is just another user thread</a> <br>
 
</div>


<div class='topic-section'>Would you use this technique?</div>
<div class='main-body'>
  
  <form action="http://www.javapractices.com/vote/AddVoteAction.do" method='post'>
    Yes<input type='radio' name='Choice' value='Y' >
    &nbsp;&nbsp;No<input type='radio' name='Choice' value='N'>
    &nbsp;&nbsp;Undecided<input type='radio' name='Choice' value="?" >
    &nbsp;&nbsp;<input type=submit value="Vote" >
    <input type='hidden' name='Operation' value='Apply'>
    <input type='hidden' name='TopicId' value='51'>
  </form>
</div>

<div style='height:10.0em;'></div>

 
 
</div>

  

 





<div align='center' class='legalese'>  
&copy; 2011 Hirondelle Systems |
<a href='../source/SourceAction-2.html'><b>Source Code</b></a><IMG class='no-margin' SRC="../images/goldstar.gif" ALT=""> |
<a href="mailto:webmaster@javapractices.com">Contact</a> |
<a href="http://creativecommons.org/licenses/by-nc-sa/1.0/">License</a> |
<a href='../apps/cjp.rss'>RSS</a>
<!-- ukey="2AC36CD2" -->
<!-- ckey="16DF3D87" -->
<br>

 Individual code snippets can be used under this <a href='../LICENSE.txt'>BSD license</a> - Last updated on June 6, 2010.<br>
 Over 150,000 unique IPs last month - <span title='Java Practices 2.6.5, Mon May 16 00:00:00 EDT 2011'>Built with</span> <a href='http://www.web4j.com/'>WEB4J</a>.<br>
 - In Memoriam : Bill Dirani -
</div>

<script src="../../www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
_uacct = "UA-2633428-1";
urchinTracker();
</script>



</body>

<!-- Mirrored from www.javapractices.com/topic/TopicAction.do;jsessionid=4FCCB481C702D708A7360133D128E359?Id=51 by HTTrack Website Copier/3.x [XR&CO'2010], Sun, 12 Jun 2011 17:28:07 GMT -->
<!-- Added by HTTrack --><meta http-equiv="content-type" content="text/html;charset=UTF-8"><!-- /Added by HTTrack -->
</html>
